package com.citytransport.prokopjuk.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import com.citytransport.prokopjuk.connectDB.ConnectionPool;
import com.citytransport.prokopjuk.vehicleDTO.Bus;
import com.citytransport.prokopjuk.vehicleDTO.InternalCombustionEngineType;

import org.apache.log4j.Logger;

public class DAOBus implements IDAOBus {
    private ConnectionPool pool;
    private DAOVehicle daoVehicle;
    static Logger logger = Logger.getLogger(DAOBus.class.getName());
    public DAOBus() {
	pool = ConnectionPool.getConnectionPool();
	daoVehicle = new DAOVehicle();
    }

    public void create(Bus bus) {
	Connection con = pool.getConnection();
	PreparedStatement prepStmt = null;
	daoVehicle.create(bus);
	try {
	    prepStmt = con
		    .prepareStatement("insert into bus values(?,?,?,?,?)");
	    prepStmt.setInt(1, bus.getID());
	    prepStmt.setBoolean(2, bus.isExistCrippleDoor());
	    prepStmt.setInt(3, bus.getDoorAmount());
	    prepStmt.setInt(4, bus.getDoorAmount());
	    prepStmt.setString(5, bus.getEngineType().toString());
	    prepStmt.executeUpdate();
	} catch (SQLException e) {
	    logger.error(e);	   
	} finally {
	    pool.returnConnecction(con);
	}
    }

    public void delete(Bus bus) {
	Connection con = pool.getConnection();
	PreparedStatement prepStmt = null;
	try {
	    prepStmt = con.prepareStatement("delete from bus where busID = ?");
	    prepStmt.setInt(1, bus.getID());
	    prepStmt.executeUpdate();
	    daoVehicle.delete(bus);
	} catch (SQLException e) {
	    logger.error(e); 
	} finally {
	    pool.returnConnecction(con);
	}

    }
    public LinkedList<Integer> getAllBusID(){
	Connection con = pool.getConnection();
	PreparedStatement prepStmt = null;
	ResultSet set = null;
	   LinkedList<Integer> index = new LinkedList<Integer>();
	    try {
		prepStmt = con.prepareStatement("select bus.busID from bus");
		 set = prepStmt.executeQuery();
		    while (set.next()) {
			index.add(set.getInt("busID"));
		    }
	    } catch (SQLException e) {
		 logger.error(e);
	    }finally{
		pool.returnConnecction(con);
	    }
	   return index;
    }
    public void deleteAllBus() {
	Connection con = pool.getConnection();
	try {
	    Statement stmt= con.createStatement();
	    stmt.executeUpdate("delete from bus");
	     ArrayList<Integer> index = new ArrayList<Integer>();
	     for(int e: index){
		 daoVehicle.delete(e);
	     }
	} catch (SQLException e) {
	    logger.error(e);
	}finally{
	    pool.returnConnecction(con);
	}
	
    }
    private InternalCombustionEngineType parseEngineType(String type){
	if(InternalCombustionEngineType.Dizel.toString().equalsIgnoreCase(type)){
	    return InternalCombustionEngineType.Dizel;
	}
	if(InternalCombustionEngineType.Gass.toString().equalsIgnoreCase(type)){
	    return InternalCombustionEngineType.Gass;
	}
	if(InternalCombustionEngineType.Carburetor.toString().equalsIgnoreCase(type)){
	    return InternalCombustionEngineType.Carburetor;
	}
	if(InternalCombustionEngineType.Rotor.toString().equalsIgnoreCase(type)){
	    return InternalCombustionEngineType.Rotor;
	}
	return null;
    }

    public Bus read(int busID) {
	Connection con = pool.getConnection();
	ResultSet set = null;
	Bus bus = null;
	PreparedStatement prepStmt = null;
	HashMap<String, String> atr = new HashMap<String, String>();
	try {
	    prepStmt = con.prepareStatement("select * from bus where busID= ?");
	    prepStmt.setInt(1, busID);
	    set = prepStmt.executeQuery();
	    set.next();
	    atr = daoVehicle.read(busID);
	    bus = new Bus(Integer.parseInt(atr.get("vehicleID")), Integer.parseInt(atr.get("seatAmount")),
		    atr.get("registrationNumber"), atr.get("model"), 
		    set.getBoolean("crippledoor"), set.getInt("doorAmount"),
		    set.getInt("engineCapacity"), 
		    parseEngineType(set.getString("engineType")));
	    
	    bus.setRouteID(Integer.parseInt(atr.get("routeID")));
	} catch (SQLException e) {
	    logger.error(e);
	}finally{
	    pool.returnConnecction(con);
	}
	return bus;
    }

    public ArrayList<Bus> readAll() {
	ArrayList<Bus> list = new ArrayList<Bus>();
	LinkedList<Integer> index = getAllBusID();
	for(int e: index){
	    list.add(read(e));
	}
	return list;
    }

    public void update(Bus bus, int seatAmount, String registrationNumber,
	    String model, int routeID, boolean cripledoor, int doorAmount,
	    int engineCapacity, InternalCombustionEngineType engineType) {
	Connection con = pool.getConnection();
	PreparedStatement prepStmt = null;
	try {
	    prepStmt = con.prepareStatement("update bus set seatAmount= ?, registrationNumber = ?, " +
	    		"model = ?,routeID = ? ,cripledoor= ?, doorAmount = ?," +
	    		"engineCapacity = ?, engineType = ? where busID = ?");
	    prepStmt.setInt(1, seatAmount);
	    prepStmt.setString(2, registrationNumber);
	    prepStmt.setString(3, model);
	    prepStmt.setBoolean(4, cripledoor);
	    prepStmt.setInt(5, doorAmount);
	    prepStmt.setInt(6, engineCapacity);
	    prepStmt.setString(7, engineType.toString());
	    prepStmt.setInt(8, bus.getID());
	    prepStmt.executeUpdate();
	    
	} catch (SQLException e) {
	    logger.error(e);
	}finally{
	    pool.returnConnecction(con);
	}
	
    }

    private LinkedList<Integer> getBusIDAtRoute(int routeID){
	LinkedList<Integer> index = new LinkedList<Integer>();
	Connection con = pool.getConnection();
	try {
	    PreparedStatement prepStmt= con.prepareStatement(
		    "Select busID from bus where busID in " +
		"(select vehicleID from vehicle where routeID = ?)");;
		prepStmt.setInt(1, routeID);
	    ResultSet resSet = prepStmt.executeQuery();
	    while(resSet.next()){
		index.add(resSet.getInt("busID"));
	    }	    
	} catch (SQLException e) {
	    logger.error(e);
	}finally{
	    pool.returnConnecction(con);	    
	}
	
	return index;
    }
    public ArrayList<Bus> readAtRoute(int routeID) {
	LinkedList<Integer> a = new LinkedList<Integer>(getBusIDAtRoute(routeID));
	ArrayList<Bus> buses = new ArrayList<Bus>();
	for(int index: a){
	    buses.add(read(index));
	}	
	return buses;
    }

}
